#ifndef CONFIG_H
#define CONFIG_H

#include <QDebug>
#include <QThread>

extern void printCurrentThreadId();



#define log_debug() (qDebug() << __FILE__ << __LINE__ << "]:")

/***********cpp17 support*************/


#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <deque>


class EventAccepter{ public: virtual ~EventAccepter(){} };
class EventSender{
public:
    virtual ~EventSender(){}
    virtual void OnAsynEvent(){}
};

//if you want to use asyn event,you must call DispatchAsynEvent in app main loop.
class EEventMgr
{
public:
    EEventMgr() :m_lMaxID(0){}
    unsigned long GetEventSenderNewID(){ m_vecIDList.push_back(++m_lMaxID); return m_lMaxID; }
    bool DelEventSenderID(long nID)
    {
        std::vector<long>::iterator it = FindID(nID);
        if (it != m_vecIDList.end())
        {
            m_vecIDList.erase(it);
            return true;
        }
        else
            return false;
    }
    bool IsExistEventSenderID(long nID){ return !(m_vecIDList.end() == FindID(nID)); }
    void AddAsynEventSender(EventSender* sender){
        if (sender){
            m_mutex.lock();
            m_mapAsynList.push_back(sender);
            m_mutex.unlock();
        }
    }
    void DispatchAsynEvent(){
        std::vector<EventSender*> tempList;
        {
            std::lock_guard<std::mutex> lock(m_mutex);
            if (m_mapAsynList.empty()) return;
            tempList.swap(m_mapAsynList);
        }
        for (EventSender* sender : tempList){
            sender->OnAsynEvent();
        }
    }
private:
    std::vector<long>::iterator FindID(int nID){
        std::vector<long>::iterator it;
        for (it = m_vecIDList.begin(); it != m_vecIDList.end();){
            if (*it == nID) return it;
            else it++;
        }
        return m_vecIDList.end();
    }
    std::mutex m_mutex;
    std::vector<long> m_vecIDList;
    std::vector<EventSender*> m_mapAsynList;
    unsigned long m_lMaxID;
};

inline EEventMgr& GetEventFactory()
{
    static EEventMgr s_EEventMgr;
    return s_EEventMgr;
}

#define Event_Def(eventName, ...) \
public: \
    template<typename... ARGS> \
    class E_##eventName: public EventSender{ \
        public: \
        E_##eventName():m_bIsSending(false), m_nSenderID(-1){m_nSenderID = GetEventFactory().GetEventSenderNewID();} \
        ~E_##eventName(){GetEventFactory().DelEventSenderID(m_nSenderID);} \
        typedef void (EventAccepter::*EventType)(__VA_ARGS__); \
        EventType eType; \
        struct Info{ \
            EventType fun; \
            EventAccepter* accepter; \
            int offset; \
            bool isSafe;\
            Info():fun(NULL), accepter(NULL), offset(0),isSafe(false){} \
    }; \
        void Add(EventAccepter* accepter, EventType func, int pointerOffset) \
    { \
            for (Info info : m_vecList){ if (info.accepter == accepter && info.fun == func) return; } \
            Info info; info.accepter = accepter; info.fun = func; info.offset = pointerOffset; \
            if(m_bIsSending) m_vecAdd.push_back(info); \
            else m_vecList.push_back(info); \
    } \
        void Send(ARGS... args){ \
            m_bIsSending = true; \
            int nSenderId = m_nSenderID; \
            for (Info& info : m_vecList){ \
                ((info.accepter+info.offset)->*info.fun)(args...); \
                if(!GetEventFactory().IsExistEventSenderID(nSenderId)) return ;} \
            m_bIsSending = false; \
            std::copy(m_vecAdd.begin(), m_vecAdd.end(), std::back_inserter(m_vecList)); m_vecAdd.clear(); \
            for (Info& info : m_vecRemove) { Remove(info.accepter, info.fun);} m_vecRemove.clear(); } \
        void Send_Asyn(ARGS... args) { \
        { \
            std::lock_guard<std::mutex> lock(m_asyncMutex); \
            m_asyncArgs.emplace_back(std::forward<ARGS>(args)...); \
        } \
        GetEventFactory().AddAsynEventSender(this); \
    } \
    virtual void OnAsynEvent() override { \
        std::deque<std::tuple<ARGS...>> argsList; \
        { \
            std::lock_guard<std::mutex> lock(m_asyncMutex); \
            argsList.swap(m_asyncArgs); \
        } \
        for (auto& argsTuple : argsList) { \
            std::apply([this](auto&&... args) { \
                this->Send(std::forward<decltype(args)>(args)...); \
            }, argsTuple); \
        } \
    } \
        void Remove(EventAccepter* accepter, EventType func) \
    { \
            if(m_bIsSending) { \
                Info info; info.accepter = accepter; info.fun = func; \
                m_vecRemove.push_back(info);} \
            else {for (auto iter = m_vecList.begin(); iter != m_vecList.end(); ){if(iter->accepter ==accepter && iter->fun == func) {iter= m_vecList.erase(iter);}else iter++;}} \
    } \
        private: \
        std::vector<Info> m_vecList; \
        std::vector<Info> m_vecAdd; \
        std::vector<Info> m_vecRemove; \
        bool m_bIsSending; \
        int m_nSenderID; \
        std::mutex m_asyncMutex; \
        std::deque<std::tuple<ARGS...>> m_asyncArgs; \
}; \
    E_##eventName<__VA_ARGS__> eventName;

#define PTO_ULONG(v) ((unsigned long long)v)

#define ERegister(sender, eventName, accepter, slot) \
    (sender)->eventName.Add(\
        reinterpret_cast<EventAccepter*>(accepter), \
        reinterpret_cast<decltype((sender)->eventName.eType)>(slot), \
        static_cast<int>(0) /* offset设为0 */)

#define EUnRegister(sender, eventName, accepter, slot) \
    if(sender){(sender)->eventName.Remove(accepter, static_cast<decltype((sender)->eventName.eType)>(slot));}
#define ESendEvent(sender, eventName, ...) (sender)->eventName.Send(__VA_ARGS__)
#define ESendEvent_Asyn(sender, eventName, ...) (sender)->eventName.Send_Asyn(__VA_ARGS__)


#if 0


#include <iostream>
#include <unistd.h>
#include <thread>
#include <atomic>

#include "EEventMgr.h"

using namespace std;


// 事件发送者类
class ThreadSafeSender : public EventSender{
public:
    Event_Def(DataEvent, int, std::string); // 带ID和数据的异步事件
    Event_Def(stringEvent, string, int);
};

// 事件接收器类
class MultiThreadAccepter : public EventAccepter {
public:
    void OnDataReceived(int id, std::string data) {
        std::cout << "[Main] Received data | ID:" << id << data
                  << " | Thread:" << std::this_thread::get_id() << "\n";
    }

    void recv(string data, int num)
    {
        std::cout << data << num << endl;
    }
};

std::atomic<bool> running(true); // 控制运行状态的原子变量

// 工作线程函数
void workerThread(ThreadSafeSender* sender, int threadID) {
    int counter = 0;
    while(running) {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        
        // 构造事件数据
        std::string data = "Thread" + std::to_string(threadID) + "_" + std::to_string(++counter);
        
        // 发送异步事件
        ESendEvent_Asyn(sender, DataEvent, threadID, "hello");
        
        std::cout << "[Worker" << threadID << "] Event sent ("  
                  << ") from:" << std::this_thread::get_id() << "\n";
    }
}

int main(int c, char *v[])
{
    ThreadSafeSender sender;
    MultiThreadAccepter accepter;

    // 注册事件处理
    ERegister(&sender, DataEvent, &accepter, &MultiThreadAccepter::OnDataReceived);
    ERegister(&sender, stringEvent, &accepter, &MultiThreadAccepter::recv);

    ESendEvent(&sender, stringEvent, "world", 100);

    // 启动两个工作线程
    std::thread worker1(workerThread, &sender, 1);
    std::thread worker2(workerThread, &sender, 2);


    // 主循环处理事件
    int mainLoopCount = 0;
    while(mainLoopCount++ < 5) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        
        // 处理异步事件队列
        std::cout << "\n--- Main dispatch (" << mainLoopCount << ") ---\n";
        GetEventFactory().DispatchAsynEvent();
    }

    // 停止工作线程
    running = false;
    worker1.join();
    worker2.join();

    // 最终处理剩余事件
    std::cout << "\n--- Final dispatch ---\n";
    GetEventFactory().DispatchAsynEvent();


    return -1;
}



#endif


#endif // CONFIG_H
